package com.tang.juc.VolatileTest;

import java.util.concurrent.TimeUnit;

/**
 * @author tlm
 * @version 1.0
 * @date 2020/4/16 10:56
 * 验证volatile的可见性
 * 1.假如int number = 0; number 变量没有用volatile修饰，没有可见性；
 */
public class VolatileDemo {
    public static void main(String[] args) {
        MyData myData = new MyData();
        //第一个线程，A线程去修改number的值
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t 进来了");
            //暂停线程3秒钟
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //3秒钟后修改number的值
            myData.setNumber100();
            //修改完成后输出值
            System.out.println(Thread.currentThread().getName()+ "\t 修改后的number值为："+myData.number);
        },"线程A").start();
        //第二个线程，main线程
        while(myData.number==0){
            //如果number为0，等待循环
        }
        System.out.println(Thread.currentThread().getName()+ "\t 任务完成，number的值为："+myData.number);
    }

}

//资源类
class MyData {
    volatile int number = 0;

    public void setNumber100() {
        this.number = 100;
    }
}
/*
    如果number不加volatile关键字修饰，则上述代码在运行后无法停止，因为线程A虽然修改了
number的值，但是对于main线程不可见（main线程并不知道主内存的值已被修改，不会去主内存拿
新值），在main线程的工作内存中，number的值仍为0，故循环不会结束，程序无法停止。
    如果number前加上volatile关键字，线程A对number的修改就变得可见，main线程会知道number
的值已被修改，去主内存中拿到number的最新值，发现不为0，退出循环，程序结束。

结论：
    volatile可以保证可见性，及时通知其他线程，主内存的值已被修改，需要从主内存拿回新的值。
 */